package com.hfb.mashibing.alip8.designpattern._12proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * Q：现有如下代码，问题：我想记录坦克的移动时间，该怎么做？
 * A：修改源码，做时间记录 V2
 * Q：那如果无法修改源码的情况下，如何实现呢？V3
 * A：用继承,继承他的实现类 V4
 * Q：应该用代理吧 V5 (持有代理对象实现类的引用，并实现代理接口)
 * Q：V6 代理有各种类型，如何实现代理的各种组合？继承？组合？
 * Q: V7 代理对象改为接口 (持有代理对象实现类的接口的引用，并实现该接口)
 * Q: V8 如果想让LogProxy 可以重用，不仅可以代理日志，
 * 还可以代理其他可以代理的类型 Object
 * （毕竟日志记录，时间计算是喝多系统都用到的东西）这个时候该怎么做呢？
 * A: 分离代理行为与被代理对象——使用jdk动态代理
 *
 * A: V9 横切 代码月业务逻辑代码 分离——AOP
 */

public class V9Tank implements MovableV9 {
    public static void main(String[] args) {
        V9Tank tank = new V9Tank();
        // reflection:通过二进制字节码分析类的属性和方法
        MovableV9 m = (MovableV9) Proxy.newProxyInstance(tank.getClass().getClassLoader(),
            new Class[]{MovableV9.class}, // tank.getClass().getInterfaces()
            new TimeProxyV9(tank));
        m.move();
    }


    @Override
    public void move() {
        System.out.println("V9 tank is moving.......");
        try {
            TimeUnit.SECONDS.sleep(new Random().nextInt(5));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("V9 tank is move end......");
    }

}

class TimeProxyV9 implements InvocationHandler{

    private MovableV9 m;

    public TimeProxyV9(MovableV9 m) {
        this.m = m;
    }
    public void before(){System.out.println("before：method start。。。");}
    public void after(){System.out.println("after：method end。。。");}
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object o = method.invoke(m, args);
        after();
        return o;
    }
}


interface MovableV9 {
    void move();
}
